﻿package com.firewolf.spring.transaction.annotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("bookService")
public class BookShopService {

	@Autowired()
	private IBookShopDao bookDao = null;
	
	/**
	 * 买书服务,需要保证在用户的余额不足时，不再买书，不要扣除书的余库
	 * 即：保证下面的方法是事物的
	 * 事务的传播行为：
     *	     在一个大的事务A中多次启用了另外一个小的事务B的时候，如果某一个事务B出错，结果怎么处理，
	 * propagation:指定事务的传播行为，即当前的事务方法被另外一个事务调用时如何使用事务
	 * 默认取值为Propagation.REQUIRED，即使用调用方法的事务，如果有一个错误，整个外层事务回滚；
	 * 
	 * Propagation.REQUIRES_NEW 表示该方法必须另启一个新事务，并在自己的事务内运行，
	 * 如果有事务在运行，就应该先挂起它；
	 * 
	 * 一些属性：
	 * 1. propagation （上面已经解释）
	 * 2. isolation， 指定事务的隔离级别，最常用的值为READ_COMMITED;
	 * 3. noRollbackFor = {Exception.class};事务的回滚方式，默认情况下声明式事务对所有
	 *    的运行时异常进行回滚，也可以通过对应的属性进行设置，通常使用默认值；
	 * 4. readOnly，指定事务是否为只读，表示这个事务只读取数据但不更新数据，这样可以帮助数据库引擎优化事务；
	 * 	      若真的是只读取的，应设置为true，否则默认为false；
	 * 5. timeout指定强制回滚之前事务可以占用的时间
	 */
	@Transactional(propagation=Propagation.REQUIRED) //事务注解，保证下面的这个方法是事务的
	public void buyBook(String bookId,String userName){
		int price = bookDao.findBookPriceById(bookId);
		bookDao.updateBookStock(bookId);
		bookDao.updateUserAccount(userName, price);
	}
}
